//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "ProcessEpitopesAndLINGOs.h"
#include "extern/Pratt2.1/menu.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <iostream>

#include <zlib.h>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define LENGTHTEXT           10000
#define DEFAULTMISSINGVALUE -100
#define MINIMUM_COINCIDENCE  20

#define COMBINATION_BY_FREQ  0
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
namespace LigandEpitopeSpace {
  
  bool EqualLINGO (TNode <String>* ligand, void* ref) {

    return (!strcmp(ligand->Info()->Out(), (char*)ref))?true:false;

  }
  
  bool MostFreqCombination (String* combinationLINGOs, void* ref) {
    
    char combination1 [combinationLINGOs->Length() + 1];
    char combination2 [((String*)ref)->Length() + 1];
    
    strcpy(combination1, combinationLINGOs->Out());
    strcpy(combination2, ((String*)ref)->Out());
    
    char* part1 = strtok(combination1, " ");
    char* part2 = strtok(combination2, " ");
    
    if (!part1 || !part2) return false;
    
    return (atoi(part1) > atoi(part2))?true:false;

  }
  
  bool LargestCombination (String* combinationLINGOs, void* ref) {
    
    return (combinationLINGOs->Length() > ((String*)ref)->Length())?true:false;

  }
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ProcessEpitopesAndLINGOs::ProcessEpitopesAndLINGOs () {
  
  this->filenameIn         = new String () ;
  this->filenameOut        = new String ();
  this->ligandEpitopeLINGO = new TListE <LigandEpitopeDataLINGO> ();
  this->filenameSMI        = new String ();
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ProcessEpitopesAndLINGOs::ProcessEpitopesAndLINGOs (const ProcessEpitopesAndLINGOs& processEpitopesAndLINGOs) {
  
  this->filenameIn         = new String (processEpitopesAndLINGOs.filenameIn) ;
  this->filenameOut        = new String (processEpitopesAndLINGOs.filenameOut);
  this->ligandEpitopeLINGO = new TListE <LigandEpitopeDataLINGO> (processEpitopesAndLINGOs.ligandEpitopeLINGO);
  this->filenameSMI        = new String (processEpitopesAndLINGOs.filenameSMI);
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ProcessEpitopesAndLINGOs::ProcessEpitopesAndLINGOs (const ProcessEpitopesAndLINGOs* processEpitopesAndLINGOs) {
  
  this->filenameIn         = new String (processEpitopesAndLINGOs->filenameIn) ;
  this->filenameOut        = new String (processEpitopesAndLINGOs->filenameOut);
  this->ligandEpitopeLINGO = new TListE <LigandEpitopeDataLINGO> (processEpitopesAndLINGOs->ligandEpitopeLINGO);
  this->filenameSMI        = new String (processEpitopesAndLINGOs->filenameSMI);
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ProcessEpitopesAndLINGOs::~ProcessEpitopesAndLINGOs () {
  
  if (this->filenameIn)         delete this->filenameIn;
  if (this->filenameOut)        delete this->filenameOut;
  if (this->ligandEpitopeLINGO) delete this->ligandEpitopeLINGO;
  if (this->filenameSMI)        delete this->filenameSMI;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ProcessEpitopesAndLINGOs::FilenameIn (String* filenameIn) {
  
  if (filenameIn) this->filenameIn->In(filenameIn);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ProcessEpitopesAndLINGOs::FilenameOut (String* filenameOut) {
  
  if (filenameOut) this->filenameOut->In(filenameOut);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ProcessEpitopesAndLINGOs::LigandEpitopeLINGO (TListE <LigandEpitopeDataLINGO>* ligandEpitopeLINGO) {
  
  if (ligandEpitopeLINGO) *(this->ligandEpitopeLINGO) = *(ligandEpitopeLINGO);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ProcessEpitopesAndLINGOs::FilenameSMI (String* filenameSMI) {
  
  if (filenameSMI) this->filenameSMI->In(filenameSMI);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ProcessEpitopesAndLINGOs::FilenameIn (void) {
  
  return this->filenameIn;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ProcessEpitopesAndLINGOs::FilenameOut (void) {
  
  return this->filenameOut;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <LigandEpitopeDataLINGO>* ProcessEpitopesAndLINGOs::LigandEpitopeLINGO (void) {
  
  return this->ligandEpitopeLINGO;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ProcessEpitopesAndLINGOs::FilenameSMI (void) {
  
  return this->filenameSMI;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ProcessEpitopesAndLINGOs::LoadDataLigandEpitope (void) {
  
  if (!this->filenameIn || !this->filenameIn->Length()) return false;

  bool isGZFile = (this->filenameIn->Contain("gz"))?1:0;

  fstream file;
  gzFile  zipFile;
  
  char    buffer [LENGTHTEXT + 1];
  
  if (isGZFile) { 
    zipFile = gzopen (this->filenameIn->Out(), "rb9"); 
    if (!zipFile) return false;
  }
  else {
    file.open (this->filenameIn->Out(), fstream::in);
    if (!file.is_open()) return false;
  }

  while (!((isGZFile)?gzeof(zipFile):file.eof())) {
    
    if (isGZFile) gzgets(zipFile, buffer, LENGTHTEXT);
    else          file.getline(buffer,    LENGTHTEXT);
    
    if (!strlen(buffer)) continue;

    LigandEpitopeDataLINGO* newLigandEpitopeDataLINGO = new LigandEpitopeDataLINGO ();

    if (newLigandEpitopeDataLINGO->LoadDataWithoutLingos(buffer)) 
      this->ligandEpitopeLINGO->Add(newLigandEpitopeDataLINGO);
    else                                             
      delete newLigandEpitopeDataLINGO;

  }

  if (isGZFile) gzclose(zipFile);
  else          file.close();

  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ProcessEpitopesAndLINGOs::LoadDataLigandEpitopeLINGO (void) {
  
  if (!this->filenameIn || !this->filenameIn->Length()) return false;

  bool isGZFile = (this->filenameIn->Contain("gz"))?1:0;

  fstream file;
  gzFile  zipFile;
  
  char    buffer [LENGTHTEXT + 1];
  
  if (isGZFile) { 
    zipFile = gzopen (this->filenameIn->Out(), "rb9"); 
    if (!zipFile) return false;
  }
  else {
    file.open (this->filenameIn->Out(), fstream::in);
    if (!file.is_open()) return false;
  }

  while (!((isGZFile)?gzeof(zipFile):file.eof())) {
    
    if (isGZFile) gzgets(zipFile, buffer, LENGTHTEXT);
    else          file.getline(buffer,    LENGTHTEXT);
    
    if (!strlen(buffer)) continue;

    LigandEpitopeDataLINGO* newLigandEpitopeDataLINGO = new LigandEpitopeDataLINGO ();

    if (newLigandEpitopeDataLINGO->LoadData(buffer)) 
      this->ligandEpitopeLINGO->Add(newLigandEpitopeDataLINGO);
    else                                             
      delete newLigandEpitopeDataLINGO;

  }

  if (isGZFile) gzclose(zipFile);
  else          file.close();

  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ProcessEpitopesAndLINGOs::LoadDataSMI (void) {
  
  if (!this->filenameSMI        || !this->filenameSMI->Length() ||
      !this->ligandEpitopeLINGO || !this->ligandEpitopeLINGO->Length()) 
    return false;

  bool isGZFile = (this->filenameSMI->Contain("gz"))?1:0;

  fstream file;
  gzFile  zipFile;
  
  char    buffer [LENGTHTEXT + 1];
  
  if (isGZFile) { 
    zipFile = gzopen (this->filenameSMI->Out(), "rb9"); 
    if (!zipFile) return false;
  }
  else {
    file.open (this->filenameSMI->Out(), fstream::in);
    if (!file.is_open()) return false;
  }
  
  int counter = 0;

  while (!((isGZFile)?gzeof(zipFile):file.eof())) {
    
    if (isGZFile) gzgets(zipFile, buffer, LENGTHTEXT);
    else          file.getline(buffer,    LENGTHTEXT);
    
    if (!strlen(buffer)) continue;

    char* part = NULL;
    char* id   = NULL;
    
    part = strtok(buffer, " \t\r\n"); if (!part) continue;
    id   = strtok(NULL,   " \t\r\n"); if (!part) continue;

    this->ligandEpitopeLINGO->SetInitial();
    while (this->ligandEpitopeLINGO->SetNext()) {
      
      if (this->ligandEpitopeLINGO->GetCurrent()->LigandName1()->Contain(id))
        this->ligandEpitopeLINGO->GetCurrent()->Smiles1()->In(part);
      
      if (this->ligandEpitopeLINGO->GetCurrent()->LigandName2()->Contain(id))
        this->ligandEpitopeLINGO->GetCurrent()->Smiles2()->In(part);
      
    }

  }

  if (isGZFile) gzclose(zipFile);
  else          file.close();

  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ProcessEpitopesAndLINGOs::WriteLigandEpitopeLINGO (void) {
  
  if (!this->filenameOut        || !this->filenameOut->Length() ||
      !this->ligandEpitopeLINGO || !this->ligandEpitopeLINGO->Length())
    return false;
  
  bool isGZFile = (this->filenameOut->Contain("gz"))?1:0;

  fstream file;
  gzFile  zipFile;
  
  if (isGZFile) { 
    zipFile = gzopen (this->filenameOut->Out(), "wb9"); 
    if (!zipFile) return false;
  }
  else {
    file.open (this->filenameOut->Out(), fstream::out);
    if (!file.is_open()) return false;
  }
  
  this->ligandEpitopeLINGO->SetInitial();
  while (this->ligandEpitopeLINGO->SetNext()) {
    
    cout << this->ligandEpitopeLINGO->GetCurrent()->ToString()->Out() << endl;
    
    if (!this->ligandEpitopeLINGO->GetCurrent()->GetCommonLingos())
      continue;
    
    cout << this->ligandEpitopeLINGO->GetCurrent()->CommonLingos()->Length() << endl;
    
    if (isGZFile) gzprintf(zipFile, "%s\n", this->ligandEpitopeLINGO->GetCurrent()->ToString()->Out());
    else          file << this->ligandEpitopeLINGO->GetCurrent()->ToString()->Out() << endl;
    
  }
  
  if (isGZFile) gzclose(zipFile);
  else          file.close();

  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ProcessEpitopesAndLINGOs::WriteLINGOVectorEpitopes (void) {
  

  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ProcessEpitopesAndLINGOs::HowOftenAParticularLingoCombinationIsFound (int cutoff) {
  
  if (!this->ligandEpitopeLINGO || !this->ligandEpitopeLINGO->Length() ||
      !this->filenameOut        || !this->filenameOut->Length())
    return false;
  
  TListE <String>* listDiffLINGOs         = new TListE <String> ();
  TListE <String>* combinationLINGOs      = new TListE <String> ();
  TListE <String>* cumulCombinationLINGOs = new TListE <String> ();

  this->ligandEpitopeLINGO->SetInitial();
  while (this->ligandEpitopeLINGO->SetNext()) {

    LigandEpitopeDataLINGO* currentLigandEpitopeDataLINGO = this->ligandEpitopeLINGO->GetCurrent();
    
    if (currentLigandEpitopeDataLINGO->MetaStructureAligment() < cutoff) continue;
    
    currentLigandEpitopeDataLINGO->CommonLingos()->SetInitial();
    while (currentLigandEpitopeDataLINGO->CommonLingos()->SetNext()) {
      
      String* currentLINGO = currentLigandEpitopeDataLINGO->CommonLingos()->GetCurrent();
      String* searchLINGO  = listDiffLINGOs->FirstOcurrence(LigandEpitopeSpace::EqualLINGO, currentLINGO->Out());
      
      if (!searchLINGO) listDiffLINGOs->Add(new String(currentLINGO));
      
    }
    
  }

  this->SearchRecursiveLINGOCombinations(listDiffLINGOs, combinationLINGOs, cumulCombinationLINGOs, cutoff);
  
  if (COMBINATION_BY_FREQ) cumulCombinationLINGOs->QuickSortListByArray(LigandEpitopeSpace::MostFreqCombination, NULL);
  else                     cumulCombinationLINGOs->QuickSortListByArray(LigandEpitopeSpace::LargestCombination,  NULL);

  fstream file;
  
  file.open (this->filenameOut->Out(), fstream::out);
  if (!file.is_open()) return false;
  
  cout << "Ordered List:" << endl;
  
  cumulCombinationLINGOs->SetInitial();
  while (cumulCombinationLINGOs->SetNext()) {
    
    String* currentCombination = cumulCombinationLINGOs->GetCurrent();

    char*   parts              = NULL;
    char    tmpCombination [currentCombination->Length() + 1];

    strcpy(tmpCombination, currentCombination->Out());

    parts = strtok(tmpCombination, " ");
    if (!parts) continue;

    TListE <String>* tmpListCombination = new TListE <String> ();

    parts = strtok(NULL, " ");
    while (parts) {
      tmpListCombination->Add(new String (parts));
      parts = strtok(NULL, " ");
    }
    
    file << "> " << currentCombination->Out() << endl;
    cout << "> " << currentCombination->Out() << endl;
    
    this->ligandEpitopeLINGO->SetInitial();
    while (this->ligandEpitopeLINGO->SetNext()) {

      int counterFound = 0;

      LigandEpitopeDataLINGO* currentLigandEpitopeDataLINGO = this->ligandEpitopeLINGO->GetCurrent();

      if (currentLigandEpitopeDataLINGO->MetaStructureAligment() < cutoff) continue;

      tmpListCombination->SetInitial();
      while (tmpListCombination->SetNext()) 
        counterFound += (currentLigandEpitopeDataLINGO->CommonLingos()->FirstOcurrence(LigandEpitopeSpace::EqualLINGO, tmpListCombination->GetCurrent()->Out()))?1:0;

      if (counterFound == tmpListCombination->Length()) {
        file << currentLigandEpitopeDataLINGO->ToString()->Out() << endl;
        cout << currentLigandEpitopeDataLINGO->ToString()->Out() << endl;
      }

    }

    if (tmpListCombination) delete tmpListCombination;
    
  }
  
  file.close();
  
  if (listDiffLINGOs)         delete listDiffLINGOs;
  if (combinationLINGOs)      delete combinationLINGOs;
  if (cumulCombinationLINGOs) delete cumulCombinationLINGOs;
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ProcessEpitopesAndLINGOs::SearchRecursiveLINGOCombinations(String& active, String& rest) {
  
  if (!rest.Length()) {
    
    String           tmpActive             = active;
    TListE <String>* listCombinationLINGOs = new TListE <String> ();
    static int       counter               = 0;
    int              coincidences          = 0;
    char*            parts                 = NULL;
    
    fstream  file;

    file.open (this->filenameOut->Out(), fstream::in | fstream::out | fstream::app);
    if (!file.is_open()) return;

    parts = strtok(tmpActive.Out(), " ");
    while (parts) {
      listCombinationLINGOs->Add(new String(parts));
      parts = strtok(NULL, " ");
    }
    
    counter++;
    
    this->ligandEpitopeLINGO->SetInitial();
    while (this->ligandEpitopeLINGO->SetNext()) {
      
      int counterFound = 0;
      
      LigandEpitopeDataLINGO* currentLigandEpitopeDataLINGO = this->ligandEpitopeLINGO->GetCurrent();
      
      listCombinationLINGOs->SetInitial();
      while (listCombinationLINGOs->SetNext()) 
        counterFound += (currentLigandEpitopeDataLINGO->CommonLingos()->FirstOcurrence(LigandEpitopeSpace::EqualLINGO, listCombinationLINGOs->GetCurrent()->Out()))?1:0;
      
      if (listCombinationLINGOs->Length() == counterFound)
        coincidences++;
      
    }
    
    if (listCombinationLINGOs) delete listCombinationLINGOs;
    
    cout << counter << "\r";
    
    if (coincidences > 1) 
      file << coincidences << " " << active.Out();
    
    file.close();
    
  }
  else {
    
    String     tmpActive;
    String     tmpSubString;

    char       tmpChar [rest.Length() + 1];
    char*      parts       = NULL;

    static int counterIter = 0;
    
    cout << "-" << active.Out() << endl;
    cout << "+" << rest.Out() << endl;
    cout << counterIter++ << endl;
    
    strcpy(tmpChar, rest.Out());
    parts = strtok(tmpChar, " ");

    tmpActive.In(active);

    if (parts) {
      tmpActive.Add(parts);
      tmpActive.Add(" ");
    }

    parts = strtok(NULL, " ");
    while (parts) {
      tmpSubString.Add(parts);
      tmpSubString.Add(" ");
      parts = strtok(NULL, " ");
    }

    this->SearchRecursiveLINGOCombinations(tmpActive, tmpSubString);
    this->SearchRecursiveLINGOCombinations(active,    tmpSubString);
    
  }
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ProcessEpitopesAndLINGOs::SearchRecursiveLINGOCombinations(TListE <String>* listDiffLINGOs, TListE <String>* listCombinations, TListE <String>* cumulCombinations, int cutoff) {
  
  if (!listCombinations || !listDiffLINGOs || !listDiffLINGOs->Length() || !this->ligandEpitopeLINGO)
    return;
  
  static int counter = 0;
  
  if (!cumulCombinations->Length()) {
    
    int coincidences;
    
    cout << "Size of List: " << listDiffLINGOs->Length() << endl;
    
    for (long i = 0; i < listDiffLINGOs->Length() - 1; i++) {
      
      for (long j = i + 1; j < listDiffLINGOs->Length(); j++) {
        
        coincidences = 0;
        
        if (strstr(listDiffLINGOs->Get(i)->Out(), listDiffLINGOs->Get(j)->Out()))
          continue;
        
        this->ligandEpitopeLINGO->SetInitial();
        while (this->ligandEpitopeLINGO->SetNext()) {

          int counterFound = 0;

          LigandEpitopeDataLINGO* currentLigandEpitopeDataLINGO = this->ligandEpitopeLINGO->GetCurrent();

          if (currentLigandEpitopeDataLINGO->MetaStructureAligment() < cutoff) continue;
          
          counterFound += (currentLigandEpitopeDataLINGO->CommonLingos()->FirstOcurrence(LigandEpitopeSpace::EqualLINGO, listDiffLINGOs->Get(i)->Out()))?1:0;
          counterFound += (currentLigandEpitopeDataLINGO->CommonLingos()->FirstOcurrence(LigandEpitopeSpace::EqualLINGO, listDiffLINGOs->Get(j)->Out()))?1:0;

          if (counterFound == 2) coincidences++;

        }

        if (coincidences >= MINIMUM_COINCIDENCE) {
          
          String* newCombination = new String ("");

          newCombination->Add(coincidences);
          newCombination->Add(" ");
          newCombination->Add(listDiffLINGOs->Get(i));
          newCombination->Add(" ");
          newCombination->Add(listDiffLINGOs->Get(j));

          listCombinations->Add(newCombination);
          cumulCombinations->Add(new String(newCombination));
          
          cout.width(6);
          cout << ++counter << " " << newCombination->Out() << endl;
          
        }
        
      }
      
    }
    
  }
  else if (cumulCombinations->Length() && listCombinations->Length()) {
    
    int coincidences;
    
    TListE <String>* tmpListCombinations = new TListE <String> ();
    
    for (long i = 0; i < listCombinations->Length(); i++) {
      
      for (long j = 0; j < listDiffLINGOs->Length(); j++) {
        
        if (strstr(listCombinations->Get(i)->Out(), listDiffLINGOs->Get(j)->Out()))
          continue;
        
        char* parts          = NULL;
        char  tmpCombination [listCombinations->Get(i)->Length() + 1];
        
        strcpy(tmpCombination, listCombinations->Get(i)->Out());
        
        parts = strtok(tmpCombination, " ");
        if (!parts) continue;
        
        TListE <String>* tmpListCombination = new TListE <String> ();
        
        parts = strtok(NULL, " ");
        while (parts) {
          tmpListCombination->Add(new String (parts));
          parts = strtok(NULL, " ");
        }
        
        tmpListCombination->Add(new String (listDiffLINGOs->Get(j)));
        
        coincidences = 0;
        
        this->ligandEpitopeLINGO->SetInitial();
        while (this->ligandEpitopeLINGO->SetNext()) {

          int counterFound = 0;

          LigandEpitopeDataLINGO* currentLigandEpitopeDataLINGO = this->ligandEpitopeLINGO->GetCurrent();
          
          if (currentLigandEpitopeDataLINGO->MetaStructureAligment() < cutoff) continue;

          tmpListCombination->SetInitial();
          while (tmpListCombination->SetNext()) 
            counterFound += (currentLigandEpitopeDataLINGO->CommonLingos()->FirstOcurrence(LigandEpitopeSpace::EqualLINGO, tmpListCombination->GetCurrent()->Out()))?1:0;

          if (counterFound == tmpListCombination->Length()) coincidences++;

        }
        
        if (coincidences >= MINIMUM_COINCIDENCE) {
          
          String* newCombination = new String ("");
          
          newCombination->Add(coincidences);
          
          tmpListCombination->SetInitial();
          while (tmpListCombination->SetNext()) {
            newCombination->Add(" ");
            newCombination->Add(tmpListCombination->GetCurrent());
          }
          
          tmpListCombinations->Add(newCombination);
          cumulCombinations->Add(new String(newCombination));
          
          cout.width(6);
          cout << ++counter << " " << newCombination->Out() << endl;
          
        }
        
        if (tmpListCombination) delete tmpListCombination;
        
      }
      
    }
    
    listCombinations->Clear();

    void* tmp           = (void*)listCombinations;
    listCombinations    = tmpListCombinations;
    tmpListCombinations = (TListE <String>*)tmp;

    if (tmpListCombinations) delete tmpListCombinations;

  }
  
  if (listCombinations->Length()) 
    this->SearchRecursiveLINGOCombinations(listDiffLINGOs, listCombinations, cumulCombinations, cutoff);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ProcessEpitopesAndLINGOs ProcessEpitopesAndLINGOs::operator= (const ProcessEpitopesAndLINGOs& processEpitopesAndLINGOs) {
  
  this->filenameIn->In(processEpitopesAndLINGOs.filenameIn) ;
  this->filenameOut->In(processEpitopesAndLINGOs.filenameOut);
  this->filenameSMI->In(processEpitopesAndLINGOs.filenameSMI);

  *(this->ligandEpitopeLINGO) = *(processEpitopesAndLINGOs.ligandEpitopeLINGO);
  
  return *this;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
